package com.cxyd.modules.wcs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cxyd.common.constant.Constants;
import com.cxyd.common.constant.WcsConstants;
import com.cxyd.common.page.PageData;
import com.cxyd.common.service.impl.CrudServiceImpl;
import com.cxyd.common.utils.ApiResult;
import com.cxyd.common.utils.ConvertUtils;
import com.cxyd.common.utils.ProcResult;
import com.cxyd.common.utils.entity.RequestData;
import com.cxyd.modules.log.service.SysLogWorkService;
import com.cxyd.modules.wcs.dao.*;
import com.cxyd.modules.wcs.dto.PostWmsDTO;
import com.cxyd.modules.wcs.entity.*;
import com.cxyd.modules.wcs.service.PcItemService;
import com.cxyd.modules.wcs.service.PostWmsService;
import com.cxyd.modules.wcs.service.ReceiveTaskService;
import com.cxyd.modules.wcs.service.TrkService;
import com.google.gson.JsonArray;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 下发指令
 *
 * @author Cycle gengruyi01@163.com
 * @since 1.0.0 2022-11-04
 */
@Service
public class PostWmsServiceImpl extends CrudServiceImpl<PostWmsDao, PostWmsEntity, PostWmsDTO> implements PostWmsService {
    @Resource
    private TrkService trkService;
    @Resource
    private AgvTrkHkDao agvTrkHkDao;
    @Resource
    private AgvTrkYfDao agvTrkYfDao;
    @Resource
    private ReceiveTaskService receiveTaskService;
    @Resource
    private SysLogWorkService logWorkService;
    @Resource
    private StnMappingDao stnMappingDao;
    @Resource
    private RouteSetDao routeSetDao;
    @Resource
    private PcItemService pcItemService;
    @Resource
    private PcItemDao pcItemDao;

    public PostWmsServiceImpl() {
    }

    @Override
    public PageData<PostWmsDTO> page(Map<String, Object> params) {
        IPage<PostWmsEntity> page = baseDao.selectPage(
                getPage(params, "update_date", false),
                getWrapper(params)
        );
        return getPageData(page, PostWmsDTO.class);
    }

    @Override
    public QueryWrapper<PostWmsEntity> getWrapper(Map<String, Object> params) {
        String contNo = (String) params.get("contNo");
        String status = (String) params.get("status");
        String curPos = (String) params.get("curPos");
        QueryWrapper<PostWmsEntity> wrapper = new QueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(contNo), "cont_no", contNo);
        wrapper.like(StringUtils.isNotBlank(curPos), "cur_pos", curPos);
        wrapper.eq(StringUtils.isNotBlank(status), "status", status);
        wrapper.orderByDesc("create_date");
        return wrapper;
    }

    @Override
    public PostWmsDTO getPostWms() {
        QueryWrapper<PostWmsEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(PostWmsEntity::getPostSt, 0)
                .isNotNull(PostWmsEntity::getRequestPk)
                .isNotNull(PostWmsEntity::getContNo)
                .orderBy(true, true, PostWmsEntity::getCreateDate)
                .last("limit 1");
        PostWmsEntity postWmsEntity = baseDao.selectOne(qw);
        return ConvertUtils.sourceToTarget(postWmsEntity, PostWmsDTO.class);
    }

    @Override
    public List<PostWmsDTO> getPostWmsList() {
        QueryWrapper<PostWmsEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(PostWmsEntity::getPostSt, 0)
                .isNotNull(PostWmsEntity::getRequestPk)
                .isNotNull(PostWmsEntity::getContNo)
                .orderBy(true, true, PostWmsEntity::getCreateDate);
        List<PostWmsEntity> postWmsEntity = baseDao.selectList(qw);
        return postWmsEntity.stream()
                .map(entity -> ConvertUtils.sourceToTarget(entity, PostWmsDTO.class))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void postWmsHandle(PostWmsDTO dto, ApiResult response) {
        String code = response.getCode();
        String msg = response.getMsg();
        String pCode = WcsConstants.PROC_CODE_SUCCESS;
        String pMsg = "容器[" + dto.getContNo() + "]到站点[" + dto.getCurPos() + "]并成功上报[MES],类型[" + dto.getNoticeType() + "]postId[" + dto.getPostId() + "]";
        int status = 0;

        //如果mes返回data中有数据，则处理生成任务
        RequestData requestData = response.getData();
        if (requestData != null) {
            String frmPos = requestData.getFrmPos();
            String toPos = requestData.getToPos();
            LambdaQueryWrapper<RouteSetEntity> query = new QueryWrapper<RouteSetEntity>().lambda().eq(RouteSetEntity::getFrmPos, frmPos).eq(RouteSetEntity::getToPos, toPos).last("limit 1");
            RouteSetEntity routeSetEntity = routeSetDao.selectOne(query);
            if (routeSetEntity == null) {
                String workName = "[流程-POST]板机请求搬送";
                String workProc = "PostWmsServiceImpl.postWmsHandle";
                pCode = "postWmsHandle_005";
                pMsg = "起点工位[" + frmPos + "]至终点工位[" + toPos + "]未在wcs_route_set中配置搬送模板!请核查!" + msg;
                logWorkService.workLogging(workName, dto.getContNo(), pCode, pMsg, "", workProc, WcsConstants.WCS_USER_NAME, 0);

                PostWmsEntity postWmsEntity = baseDao.selectById(dto.getPostId());
//        核验类型是[通知]or[完成]
                postWmsEntity.setPostSt(WcsConstants.POST_STATUS_ERROR);
                postWmsEntity.setAckMsg(pCode + ":" +pMsg);
                postWmsEntity.setUpdater(WcsConstants.WCS_USER_ID);
                postWmsEntity.setUpdateDate(new Date());
                baseDao.updateById(postWmsEntity);
                return;
            }

            //生成 trk任务
            TrkEntity wcsTrk = new TrkEntity();
            wcsTrk.setRequestPk(requestData.getRequestPk());
            wcsTrk.setContNo(requestData.getContNo());
            wcsTrk.setDvcNo(WcsConstants.TRK_DVC_NO_HK);
            wcsTrk.setTrkSt(WcsConstants.TRK_STATUS_START);
            wcsTrk.setTrkType(routeSetEntity.getTrkType());
            wcsTrk.setTrkPrty(1);
            wcsTrk.setFrmPos(frmPos);
            wcsTrk.setToPos(toPos);
            wcsTrk.setCurPos(frmPos);
            wcsTrk.setIsFull(requestData.getIsFull());
            wcsTrk.setCreator(WcsConstants.MES_USER_ID);
            wcsTrk.setCreateDate(new Date());

            try {
                trkService.insert(wcsTrk);
                status = WcsConstants.POST_STATUS_SUCCESS;
            } catch (Exception e) {
                String workName = "[流程-POST]" + dto.getCurPos() + "任务请求";
                String workProc = "PostWmsServiceImpl.postWmsHandle";
                pCode = "postWmsHandle_004";
                pMsg = "生成trk任务失败！" + e.getMessage();
                logWorkService.workLogging(workName, dto.getContNo(), pCode, pMsg, "", workProc, WcsConstants.WCS_USER_NAME, 0);

                PostWmsEntity postWmsEntity = baseDao.selectById(dto.getPostId());
                postWmsEntity.setPostSt(WcsConstants.POST_STATUS_ERROR);
                postWmsEntity.setAckMsg(pCode + ":" +pMsg);
                postWmsEntity.setUpdater(WcsConstants.WCS_USER_ID);
                postWmsEntity.setUpdateDate(new Date());
                baseDao.updateById(postWmsEntity);
                return;
            }
        } else if (Constants.SUCCESS.equals(response.getCode())) {
            status = WcsConstants.POST_STATUS_SUCCESS;
//            成功下发更新[wcs_trk]任务状态
        } else if (Constants.FAIL.equals(response.getCode())) {
            //mes反馈创建任务失败就直接返回，定时器继续请求
            PostWmsEntity postWmsEntity = baseDao.selectById(dto.getPostId());
//            postWmsEntity.setPostSt(WcsConstants.POST_STATUS_ERROR);
            postWmsEntity.setAckMsg(code + ":" +msg);
            postWmsEntity.setUpdater(WcsConstants.WCS_USER_ID);
            postWmsEntity.setUpdateDate(new Date());
            baseDao.updateById(postWmsEntity);
            return;
        } else {
            status = WcsConstants.POST_STATUS_ERROR;
            pCode = "postWmsHandle_001";
            pMsg = "requestPk[" + dto.getRequestPk() + "]搬送信号上报失败!causeBy:" + msg;
        }

//        开始时间-start
        Instant start = Instant.now();
//        1.更新post_wms记录状态
        PostWmsEntity postWmsEntity = baseDao.selectById(dto.getPostId());
//        核验类型是[通知]or[完成]
        postWmsEntity.setPostSt(status);
        postWmsEntity.setAckMsg(code + ":" + msg);
        postWmsEntity.setUpdater(WcsConstants.WCS_USER_ID);
        postWmsEntity.setUpdateDate(new Date());
        baseDao.updateById(postWmsEntity);
//        2.匹配对应的wcs_trk搬送任务
        TrkEntity wcsTrk = trkService.selectByContNo(dto.getContNo());
        if (wcsTrk == null) {
            return;
        }
//        任务上报成功则转移数据
        if (status == WcsConstants.POST_STATUS_SUCCESS) {
            baseDao.backupPostWms(dto.getContNo());
            baseDao.deleteById(dto.getPostId());
//            只有当通知类型为完成才会对任务进行转移
            if (WcsConstants.POST_TYPE_DONE.equals(dto.getNoticeType())) {
//        2.更新wcs_trk任务状态并转移(将同组的任务都进行转移)
                trkService.updateTrkByGroupNo(wcsTrk.getGroupNo());
//        3.指令信息转移
                receiveTaskService.updateReceiveTaskByContNo(dto.getContNo());
            }
        }
        //        结束时间-end
        Instant end = Instant.now();
        String workName = "[流程-POST]任务信息上报";
        String workProc = "PostWmsServiceImpl.postWmsHandle";
//        计算耗时
        Duration times = Duration.between(start, end);
        logWorkService.workLogging(workName, dto.getContNo(), pCode, pMsg, "", workProc, WcsConstants.WCS_USER_NAME, times.toMillis());
    }

    @Override
    public ProcResult postHandler(Map<String, Object> params) {
        //        接收指令ID以及操作方式
        String postId = (String) params.get("postId");
        String operateType = (String) params.get("operateType");
//        判断任务是否存在(不存在报错)
        PostWmsEntity postWmsEntity = baseDao.selectById(postId);
        if (postWmsEntity == null) {
            return new ProcResult().result("postHandler_003", "指令[" + postId + "]不存在!");
        }
//        根据操作方式进行数据处理(REPEAT/DONE/CANCEL/DELETE)
        if (WcsConstants.TASK_FORCE_REPEAT_OPERATE.equals(operateType)) {
//          只能重发异常状态的任务
            if (WcsConstants.TRK_STATUS_ERROR != postWmsEntity.getPostSt()) {
                return new ProcResult().result("postHandler_004", "只有[异常]状态下的指令允许重发!");
            }
//          将状态设置为初始
            postWmsEntity.setPostSt(WcsConstants.TRK_STATUS_START);
//          备注信息人为操作
            postWmsEntity.setComments("人工将指令重新下发!");
//          更新时间
            postWmsEntity.setUpdateDate(new Date());
        } else {
            return new ProcResult().result("postHandler_005", "作业类型不存在!");
        }
        baseDao.updateById(postWmsEntity);
        return new ProcResult().result("0", "success");
    }
}